%include	"boot.inc"

SECTION MBR vstart=07c00h	;程序开始地址
	mov ax, cs		;使用cs初始化其他寄存器，
	mov ds, ax		;bios 通过 jmp 0:07c00h 跳转到MBR的开始地址
	mov es, ax		;所以 cs 是 0.
	mov ss, ax
	mov fs, ax
	mov sp, 07c00h		;初始化栈指针

;test
	mov esi,	eax
	mov eax,	LOADER_START_SECTOR
	mov al, al
	mov eax, esi

;清屏，使用0x10中断的0x6号功能
	
	mov ax,	0600h
	mov bx, 0700h
	mov cx, 0
	mov dx,	0184fh
	
	int	010h

;获取光标,0x10中断的 3号功能.

	mov	ah, 3	;3号功能获取光标
	mov	bh, 1	;bh寄存器存储获取光标位置的页号，从0开始。此处填1可以看成将光标移动到最开始
	int 010h

;打印字符串

	mov ax, message
	mov bp, ax	;es:bp=显示字符串的地址.
	
	mov cx, 6	;字符串长度，不包括'\0'
	mov ax, 01301h	;ah=13在teletype模式下显示字符串. al=1,显示属性在bl，显示后光标位置改变。
	mov bx, 02h
	
	int 010h

	

	

	mov	eax,	LOADER_START_SECTOR	;起始扇区的lba地址
	mov	bx,	LOADER_BASE_ADDR	;写入地址
	mov	cx,	1			;读入的扇区数
	call	rd_disk_m_16			;读取扇区的数据到写入地址
	
	jmp	LOADER_BASE_ADDR		;跳转到写入地址，执行磁盘上读取的代码

rd_disk_m_16:			;eax=扇区号, cx=读取扇区数, bx=读取数据后写入内存的地址	
	mov	esi,	eax	;备份eax扇区号，备份cx读取的扇区数
	mov	di,	cx

;从端口读写数据必须使用al，如果端口地址是2个字节，使用dx存储端口地址，否则直接用地址。
;设置要读取的扇区数
;0x01f2端口传入要读取的扇区数。因为是8位端口，所以可以读取255个扇区。如果值为0,表示读取256个扇区。
;此端口的值，在每次读取一个扇区后，会减一。
	mov	dx,	01f2h
	mov	al,	cl
	out	dx,	al
	mov	eax,	esi

;lba扇区号，28位，要分4此存入端口0x01f3,0x01f4,0x01f5,0x01f6
;将lba地址存入0x1f3-0x1f6

	;lba地址0-7位写入端口0x1f3
	mov	dx,	0x1f3
	out	dx,	al

	;lba地址8-15位写入0x1f4
	mov	cl,	8
	shr	eax,	cl
	mov 	dx,	0x1f4
	out 	dx,	al

	;lba地址16-23位写入端口0x1f5
	shr	eax,	cl
	mov	dx,	0x1f5
	out	dx,	al

	
	shr	eax,	cl
	and	al,	0x0f
	or	al,	0xe0
	mov	dx,	0x1f6
	out	dx,	al


;向0x01f7端口写入0x20，请求读硬盘
	;向0x1f7写入读命令
	mov	dx,	0x1f7
	mov	al,	0x20
	out	dx,	al

;0x01f7既是命来端口，也是状态端口。从该端口读取数据，下标从0开始，第7位为1,表示硬盘忙。第7位为0表示就绪，第3位为1表示准备好传数据。
.not_ready:
	nop
	in	al,	dx
	and	al,	0x88	;第3位为1表示硬盘控制器已经准备好数据传输，第7位为1表示硬盘忙
	cmp	al,	0x08
	jnz	.not_ready

;从0x1f0端口读取数据
	mov	ax,	di
	mov	dx,	256
	mul	dx
	mov	cx,	ax
	mov	dx,	0x1f0
.go_on_read:
	in	ax,	dx
	mov	[bx],	ax
	add	bx,	2
	loop	.go_on_read	;loop: cx=cx-1, if cx > 0 then go to loop
	ret




	message db "My MBR"
	times 510-($-$$) db 0
	db 055h, 0aah
